﻿Class DefaultContentPublisher(Of T As IContent)
    Implements IContentPublisher

    Private _content_type As ContentType
    Private _write_properties As IEnumerable(Of ContentProperty)
    Private _reference_properties As IEnumerable(Of ContentReference)
    Private _property_instancer As New Dictionary(Of MysteryPropertyAttribute, IActivator)

    Private ref_text As ReferenceText

    Sub New()
        _content_type = getMystery().AssemblyRegister.getMysteryClassAttribute(Of ContentType, T)()

        Dim all As IEnumerable(Of ContentProperty) = getMystery().AssemblyRegister.getMysteryPropertyAttributes(Of ContentProperty, T)()
        _write_properties = New HashSet(Of ContentProperty)((From x As ContentProperty In all Select x Where x.retrive IsNot Nothing))
        Dim references As IEnumerable(Of ContentReference) = getMystery.AssemblyRegister.getMysteryPropertyAttributes(Of ContentReference, T)()
        _reference_properties = New HashSet(Of ContentReference)((From x As ContentReference In references Select x Where x.retrive IsNot Nothing))


        Dim fa As FastActivator = getGlobalObject(Of FastActivator)()

        For Each wp As ContentProperty In _write_properties
            'fedding _property_instancer
            Dim pt As Type = wp.used_in.PropertyType.GetGenericArguments.FirstOrDefault
            _property_instancer(wp) = fa.getActivator(wp.used_in.PropertyType)
        Next

        ref_text = GetType(T).getFirstAttribute(Of ReferenceText)()

        For Each wp As ContentReference In _reference_properties
            'fedding _property_instancer
            Dim target_type As Type = wp.used_in.PropertyType.GetGenericArguments.FirstOrDefault
            _property_instancer(wp) = fa.getActivator(wp.used_in.PropertyType)
        Next

    End Sub


    Public Function generate(item As IContent) As Xml.XmlDocument Implements IContentPublisher.generate
        Dim doc As New Xml.XmlDocument
        Dim root As Xml.XmlElement = doc.CreateElement(_content_type.name)
        doc.AppendChild(root)
        Dim guid_attr As Xml.XmlAttribute = doc.CreateAttribute("guid")
        guid_attr.Value = item.guid.ToString
        root.Attributes.Append(guid_attr)

        If ref_text IsNot Nothing Then
            Dim value As String = ref_text.getReferenceText(item)
            Dim property_attr As Xml.XmlAttribute = doc.CreateAttribute(GetType(ReferenceText).Name)
            property_attr.Value = value
            root.Attributes.Append(property_attr)
        End If

        For Each wp As ContentProperty In _write_properties
            Dim pv As ContentPropertyValue = wp.retrive(item)
            Dim value As Object = If(pv Is Nothing, "", pv.getValue())
            If value Is Nothing Then value = ""

            'I have dates , when the hell they fix it, date.min is out of range in sql
            If TypeOf (value) Is Date AndAlso value = Date.MinValue Then
                value = ""
            Else
                value = value.ToString
            End If

            Dim property_ele As Xml.XmlElement = doc.CreateElement(wp.name)
            root.AppendChild(property_ele)
            property_ele.InnerText = value

            Dim property_attr As Xml.XmlAttribute = doc.CreateAttribute("type")
            Dim property_type As Type = wp.used_in.PropertyType.GetGenericArguments.FirstOrDefault
            property_attr.Value = property_type.Name
            property_ele.Attributes.Append(property_attr)

            'something special for selections
            Dim dict_attr As StringPropertyDictAttr = wp.used_in.getMysteryAttribute(Of StringPropertyDictAttr)()
            If dict_attr IsNot Nothing Then
                property_attr = doc.CreateAttribute("ref")
                property_attr.Value = dict_attr.getDictionary(item).getLabelFor(value)
                property_ele.Attributes.Append(property_attr)
            End If

            property_attr = doc.CreateAttribute("ref_type")
            property_attr.Value = False
            property_ele.Attributes.Append(property_attr)

        Next

        For Each rp As ContentReference In _reference_properties

            Dim pv As BaseContentReference = rp.retrive()(item)

            Dim referefece_ele As Xml.XmlElement = doc.CreateElement(rp.name)
            root.AppendChild(referefece_ele)

            Dim property_attr As Xml.XmlAttribute = doc.CreateAttribute("type")
            Dim refered_type As Type = rp.used_in.PropertyType.GetGenericArguments.FirstOrDefault

            property_attr.Value = refered_type.getMysteryAttribute(Of ContentType)().name
            referefece_ele.Attributes.Append(property_attr)

            property_attr = doc.CreateAttribute("ref_type")
            property_attr.Value = True
            referefece_ele.Attributes.Append(property_attr)

            Dim is_ref_text As ReferenceText = refered_type.getFirstAttribute(Of ReferenceText)()

            For Each c As IContent In pv.getAsEnum()
                Dim referefece_value As Xml.XmlElement = doc.CreateElement("value")
                referefece_ele.AppendChild(referefece_value)
                Dim referefece_ele_attr As Xml.XmlAttribute = doc.CreateAttribute("guid")
                referefece_ele_attr.Value = c.guid.ToString
                referefece_value.Attributes.Append(referefece_ele_attr)
                If is_ref_text IsNot Nothing Then
                    referefece_ele_attr = doc.CreateAttribute("ref")
                    referefece_ele_attr.Value = is_ref_text.getReferenceText(c)
                    referefece_value.Attributes.Append(referefece_ele_attr)
                End If
            Next

        Next


        Return doc

    End Function



End Class

